package com.example.utils;

import com.example.domain.UserDetail;
import com.example.domain.dto.SysUserDto;
import com.example.domain.vo.LoginUserVo;
import io.jsonwebtoken.*;
import io.jsonwebtoken.security.Keys;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import java.nio.charset.StandardCharsets;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.interfaces.ECPrivateKey;
import java.util.Base64;
import java.util.Date;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * @author ljs
 * @date 2025/7/22
 */
@Component
public class JWTUtils {

    @Autowired
    public RedisCacheUtil redisCacheUtil;


    // 密钥（建议从配置文件读取，至少32位）
   // private static final String SECRET_KEY = "vivid-cloud-alibaba-server";
    private static final String SECRET_KEY = "nBwG51M8hxM1SJIIrP8uvVraC1zQh49hNSeV5MNgPXKIrKfqx9ZmSpM/UXDo49AFWyy/W9Mwsi/jvth8CAq6+w==";

    // Token 过期时间（例如：24小时）
    private static final long EXPIRATION_TIME = 30 * 60 * 1000; // 毫秒

    // 显式将字符串转换为 SecretKey（HS512 专用）
    private static final SecretKey SIGNING_KEY = Keys.hmacShaKeyFor(SECRET_KEY.getBytes(StandardCharsets.UTF_8));

    /**
     * 根据用户信息创建 JWT Token
     */
    public String createToken(UserDetail userDetail){
        // 当前时间
        Long currentTime = System.currentTimeMillis();
        userDetail.setCurrentTime(currentTime);

        //redis的getkey
        String redisKey = UUID.randomUUID().toString().replace("-","") + SECRET_KEY;

        refreshToken(redisKey,userDetail);

        // 构建 Token
        return Jwts.builder()
                // 设置自定义claims（可选，存储用户信息）
                .claim("redisKey", redisKey) // 存入用户ID
                // 设置主题（可选，通常为用户名或唯一标识）
                .setSubject(userDetail.getSysUser().getUsername())
                // 设置签名算法和密钥（必须）
                .signWith(SignatureAlgorithm.HS512,SIGNING_KEY)
               // .signWith(privateKey, SignatureAlgorithm.ES256)

                // 生成 Token 字符串
                .compact();
    }

    /**
     * 解析 Token 并返回其中的 claims（包含用户信息）
     * @param token 待解析的 Token 字符串
     * @return 包含用户信息的 Claims 对象
     * @throws JwtException 当 Token 无效、过期、签名错误时抛出
     */
    public static Claims parseToken(String token) throws JwtException {
        try {
            // 解析 Token，验证签名和过期时间
            return Jwts.parserBuilder()
                    // 设置签名密钥（必须与创建时一致）
                    .setSigningKey(SIGNING_KEY)
                    .build()
                    // 解析 Token 字符串
                    .parseClaimsJws(token)
                    // 获取 payload 中的 claims
                    .getBody();
        } catch (ExpiredJwtException e) {
            // Token 已过期
            throw new JwtException("Token 已过期", e);
        } catch (UnsupportedJwtException e) {
            // Token 格式不支持
            throw new JwtException("不支持的 Token 格式", e);
        } catch (MalformedJwtException e) {
            // Token 格式错误（如被篡改）
            throw new JwtException("Token 格式错误", e);
        } catch (SignatureException e) {
            // 签名验证失败（如密钥不一致）
            throw new JwtException("Token 签名无效", e);
        } catch (IllegalArgumentException e) {
            // Token 为空或参数错误
            throw new JwtException("Token 为空或无效", e);
        }
    }

    /**
     * 提取用户信息
     */
    public UserDetail getUserFromToken(String token) throws JwtException {
        Claims claims = parseToken(token);
        String redisKey = (String) claims.get("redisKey");
        UserDetail cacheObject = redisCacheUtil.getCacheObject(redisKey);
        if (cacheObject != null) {
            long nowTime = System.currentTimeMillis();
            Long currentTime = cacheObject.getCurrentTime();
            if (nowTime - currentTime > EXPIRATION_TIME) {
                refreshToken(redisKey,cacheObject);
            }
            return cacheObject;
        }
        return null; // 获取创建时设置的 subject（通常为用户名）
    }

    /**
     * 用户信息存入redis中
     * @param redisKey
     * @param userDetail
     */
    public void refreshToken(String redisKey, UserDetail userDetail){
        redisCacheUtil.setCacheObject(redisKey,userDetail,30, TimeUnit.MINUTES);

    }

    // 生成 ES256 所需的椭圆曲线密钥对（256位）
    private static KeyPair generateEcKeyPair() throws Exception {
        KeyPairGenerator keyGen = KeyPairGenerator.getInstance("EC"); // 椭圆曲线算法
        keyGen.initialize(256); // ES256 必须用 256 位密钥
        return keyGen.generateKeyPair();
    }


    public static void main(String[] args) throws Exception {
        JWTUtils jwtUtils = new JWTUtils();
        UserDetail userFromToken = jwtUtils.getUserFromToken("eyJhbGciOiJIUzUxMiJ9.eyJyZWRpc0tleSI6IjFjYjEzOGZjNzkzYjRiYTg5M2Q0ZWMyZmExYTgyOTNmbkJ3RzUxTThoeE0xU0pJSXJQOHV2VnJhQzF6UWg0OWhOU2VWNU1OZ1BYS0lyS2ZxeDlabVNwTS9VWERvNDlBRld5eS9XOU13c2kvanZ0aDhDQXE2K3c9PSIsInN1YiI6ImFkbWluIn0.wMaf_x5TOwuFUfd6lhMx9dubCxGAkxqEtSR6Oz-AOmCzwsZ5WSbvAGDkvV_CE9eRJ9Nhpqic6Eb5Epkt6rnkYA");


//        // 获取HmacSHA512算法的KeyGenerator实例
//        KeyGenerator keyGen = KeyGenerator.getInstance("HmacSHA512");
//        // 生成密钥
//        SecretKey secretKey = keyGen.generateKey();
//        // 将密钥编码为Base64字符串，以便存储或传输
//        String secretKeyStr = Base64.getEncoder().encodeToString(secretKey.getEncoded());
//        System.out.println(secretKeyStr);
    }
}

